package com.impossible.chan;

import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.DateAxis;
import org.jfree.chart.plot.XYPlot;
import org.jfree.data.category.DefaultCategoryDataset;
import org.jfree.data.time.Millisecond;
import org.jfree.data.time.TimeSeries;
import org.jfree.data.time.TimeSeriesCollection;

import java.math.BigDecimal;
import java.sql.*;
import java.sql.Date;
import java.text.SimpleDateFormat;
import java.util.*;
import javax.swing.*;
import java.awt.*;
import java.util.List;

public class Hello {

    // 数据库连接配置
    private static final String URL = "jdbc:mysql://hk-cynosdbmysql-grp-5hoa8zdl.sql.tencentcdb.com:20331/price?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true";
    private static final String USER = "zzt";  // 替换为实际的数据库用户名
    private static final String PASSWORD = "LonelyDick@123";  // 替换为实际的数据库密码

    // 日期格式化工具
    private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    public static void main(String[] args) {
        // JVM 运行时
        Runtime runtime = Runtime.getRuntime();

        String coinName = "BTC";

        List<PriceData> price1ds = getPriceData("price_1d", 365, coinName);
        List<PriceData> price4hs = getPriceData("price_4h", 2000, coinName);
        List<PriceData> price30ms = getPriceData("price_30m", 2000, coinName);

        // 按币种分组并计算中枢
        System.out.println("==== 1d ====");
        calculateMiddleZoneByCoin(price1ds, "1 Day");

        System.out.println("==== 4h ====");
        calculateMiddleZoneByCoin(price4hs, "4 Hour");

        System.out.println("==== 30m ====");
        calculateMiddleZoneByCoin(price30ms, "30 minute");

        // 最大内存
        long maxMemory = runtime.maxMemory();
        // 已分配内存
        long totalMemory = runtime.totalMemory();
        // 空闲内存
        long freeMemory = runtime.freeMemory();
        // 使用内存
        long usedMemory = totalMemory - freeMemory;

        System.out.println("最大内存 (Max Memory): " + maxMemory / 1024 / 1024 + " MB");
        System.out.println("已分配内存 (Total Memory): " + totalMemory / 1024 / 1024 + " MB");
        System.out.println("空闲内存 (Free Memory): " + freeMemory / 1024 / 1024 + " MB");
        System.out.println("使用内存 (Used Memory): " + usedMemory / 1024 / 1024 + " MB");
    }

    // 获取数据
    public static List<PriceData> getPriceData(String tableName, int limit, String coinName) {
        List<PriceData> dataList = new ArrayList<>();

        String query = "SELECT ts, o, h, l, c, vol, vol_ccy, vol_ccy_quote, confirm, coin_name FROM " + tableName +" where coin_name ='"+coinName+"' order by ts desc limit "+ limit;
        //String query = "SELECT ts, o, h, l, c, vol, vol_ccy, vol_ccy_quote, confirm, coin_name FROM " + tableName +" order by ts asc";

        try (Connection conn = DriverManager.getConnection(URL, USER, PASSWORD);
             Statement stmt = conn.createStatement();
             ResultSet rs = stmt.executeQuery(query)) {

            while (rs.next()) {
                PriceData data = new PriceData(
                        rs.getLong("ts"),
                        rs.getBigDecimal("o"),
                        rs.getBigDecimal("h"),
                        rs.getBigDecimal("l"),
                        rs.getBigDecimal("c"),
                        rs.getBigDecimal("vol"),
                        rs.getBigDecimal("vol_ccy"),
                        rs.getBigDecimal("vol_ccy_quote"),
                        rs.getString("confirm"),
                        rs.getString("coin_name")
                );
                dataList.add(data);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        Collections.reverse(dataList);
        return dataList;
    }

    // 按币种计算中枢并输出
    public static void calculateMiddleZoneByCoin(List<PriceData> priceDataList, String dataType) {
        // 按币种分组
        Map<String, List<PriceData>> coinDataMap = new HashMap<>();
        for (PriceData data : priceDataList) {
            coinDataMap.computeIfAbsent(data.getCoinName(), k -> new ArrayList<>()).add(data);
        }

        // 遍历每个币种的价格数据，计算中枢
        for (Map.Entry<String, List<PriceData>> entry : coinDataMap.entrySet()) {
            String coinName = entry.getKey();
            List<PriceData> coinData = entry.getValue();

            System.out.println("币种: " + coinName);
            System.out.println("Data Type: " + dataType);

            // 获取合并后的k线数据
            List<MergeK> mergeKList = new ArrayList();
            coinData.forEach( price ->{
                mergeKList.add(new MergeK(price.getTs(), price.getH(), price.getL()));
            } );
            List<BaseDing> dingList = MergePriceUtil.getTbList(mergeKList);
            TimeSeries series = new TimeSeries(priceDataList.get(0).getCoinName());
            int i = 0;
            for(BaseDing ding : dingList) {
                series.add(new Millisecond(new Date(ding.getTs())), ding.getValue().doubleValue());
                i++;
            }
            // 创建数据集
            TimeSeriesCollection dataset = new TimeSeriesCollection();
            dataset.addSeries(series);

            // 创建折线图
            JFreeChart chart = ChartFactory.createTimeSeriesChart(
                    priceDataList.get(0).getCoinName()+" "+ dataType, // 图表标题
                    "time",         // X 轴标签
                    "price",           // Y 轴标签
                    dataset,        // 数据集
                    true,           // 显示图例
                    true,           // 工具提示
                    false           // 不生成 URL
            );

            // 设置 X 轴格式
            XYPlot plot = (XYPlot) chart.getPlot();
            DateAxis axis = (DateAxis) plot.getDomainAxis();
            axis.setDateFormatOverride(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));

            // 显示图表
            ChartPanel chartPanel = new ChartPanel(chart);
            JFrame frame = new JFrame(priceDataList.get(0).getCoinName()+" "+ dataType );
            frame.add(chartPanel);
            frame.setSize(800, 600);
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setVisible(true);

//            // 计算中枢区间
//            List<MiddleZone> middleZones = calculateZhengzhuForCoin(dingList);
//
//            // 输出日志：按币种和区间输出中枢
//            if (middleZones.isEmpty()) {
//                System.out.println("No middle zones found for " + coinName);
//            } else {
//                for (MiddleZone zone : middleZones) {
//                    System.out.println("币种: " + coinName + ", 中枢: [ 中低 " + zone.getLow() + ", 中高" + zone.getHigh()
//                            + ", 最高" + zone.getZHigh()
//                            + ", 最低" + zone.getZLow()
//                            + "] 开始 " + DATE_FORMAT.format(new Date(zone.getStartTimestamp()))
//                            + " 结束 " + DATE_FORMAT.format(new Date(zone.getEndTimestamp())));
//                }
//            }
//            System.out.println();
        }
    }

    // 按照缠论的规则计算中枢区间
    public static List<MiddleZone> calculateZhengzhuForCoin(List<BaseDing> dingDataList) {
        List<MiddleZone> middleZones = new ArrayList<>();

        int i = 0;
        // 遍历所有的价格数据来计算时间段中的中枢
        while(true){
            if(i >= dingDataList.size() -2){
                break;
            }
            int dingCum = 2;
            MiddleZone middleZone = new MiddleZone();
            BaseDing thisDing = dingDataList.get(i);
            BaseDing nextDing = dingDataList.get(i+1);
            middleZone.setStartTimestamp(thisDing.getTs());
            middleZone.setEndTimestamp(nextDing.getTs());
            if(thisDing.getDingType() ==1 ){
                middleZone.setHigh(thisDing.getValue());
                middleZone.setZHigh(thisDing.getValue());
                middleZone.setLow(nextDing.getValue());
                middleZone.setZLow(nextDing.getValue());
            }else {
                middleZone.setHigh(nextDing.getValue());
                middleZone.setZHigh(nextDing.getValue());
                middleZone.setZLow(thisDing.getValue());
                middleZone.setLow(thisDing.getValue());
            }
            for(int j = i+2; j< dingDataList.size(); j++){
                if(checkExitMiddleZone(middleZone, dingDataList.get(j))){
                    dingCum ++;
                }else {
                    break;
                }
            }
            if(dingCum>3){
                middleZones.add(middleZone);
                i = i+dingCum;
            }else {
                i = i +1;
            }

        }
        return middleZones;
    }

    // 检查是否离开中枢
    public static boolean checkExitMiddleZone(MiddleZone zone, BaseDing ding) {
        if(ding.getDingType() == 1 && ding.getValue().compareTo(zone.getLow()) < 0){
            return false;
        }
        if(ding.getDingType() == 0 && ding.getValue().compareTo(zone.getHigh()) >0){
            return false;
        }
        if(ding.getDingType() == 1 && ding.getValue().compareTo(zone.getHigh()) < 0){
            zone.setHigh(ding.getValue());
        }
        if(ding.getDingType() == 0 && ding.getValue().compareTo(zone.getLow()) >0){
            zone.setLow(ding.getValue());
        }
        if(ding.getDingType() == 1 && ding.getValue().compareTo(zone.getHigh()) > 0){
            zone.setZHigh(ding.getValue());
        }
        if(ding.getDingType() == 0 && ding.getValue().compareTo(zone.getLow()) < 0){
            zone.setZLow(ding.getValue());
        }
        zone.setEndTimestamp(ding.getTs());
        return true;
    }

}
